package com.hang.ad.service.impl;

import com.hang.ad.constant.Constants;
import com.hang.ad.dao.AdPlanDao;
import com.hang.ad.dao.AdUnitDao;
import com.hang.ad.dao.unit_condition.AdUnitDistrictDao;
import com.hang.ad.dao.unit_condition.AdUnitItDao;
import com.hang.ad.dao.unit_condition.AdUnitKeywordDao;
import com.hang.ad.dao.unit_condition.CreativeUnitDao;
import com.hang.ad.entity.AdPlan;
import com.hang.ad.entity.AdUnit;
import com.hang.ad.entity.unit_condition.AdUnitDistrict;
import com.hang.ad.entity.unit_condition.AdUnitIt;
import com.hang.ad.entity.unit_condition.AdUnitKeyword;
import com.hang.ad.entity.unit_condition.CreativeUnit;
import com.hang.ad.exceptions.AdException;
import com.hang.ad.service.IAdUnitService;
import com.hang.ad.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class AdUnitServiceImpl implements IAdUnitService {
    @Autowired
    AdPlanDao adPlanDao;
    @Autowired
    AdUnitDao adUnitDao;
    @Autowired
    AdUnitKeywordDao adUnitKeywordDao;
    @Autowired
    AdUnitItDao adUnitItDao;
    @Autowired
    AdUnitDistrictDao adUnitDistrictDao;
    @Autowired
    CreativeUnitDao creativeUnitDao;

    @Override
    @Transactional
    public AdUnitResponse createUnit(AdUnitRequest request) throws AdException {
        if (!request.createValidate()){
            throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR);
        }
        Optional<AdPlan> optional = adPlanDao.findById(request.getPlanId());
        if (!optional.isPresent()){
            throw new AdException(Constants.ErrorMsg.CAN_NOT_FIND_RECORD);
        }
        AdUnit unit = adUnitDao.findByPlanIdAndUnitName(request.getPlanId(), request.getUnitName());

        if (unit != null){
            throw new AdException(Constants.ErrorMsg.SAME_UNIT_NAME);
        }
        AdUnit adUnit = adUnitDao.save(new AdUnit(request.getPlanId(), request.getUnitName(), request.getPositionType(), request.getBudget()));

        return new AdUnitResponse(adUnit.getId(),adUnit.getUnitName());
    }

    @Override
    @Transactional
    public AdUnitKeywordResponse createUnitKeyword(AdUnitKeywordRequest request) throws AdException {
        List<Long> ids = request.getAdUnitKeywords().stream()
                .map(AdUnitKeywordRequest.AdUnitKeyword::getUnitId).collect(Collectors.toList());
        if (!isUnitExist(ids)){
            throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR);
        }

        List<AdUnitKeyword> keywordList = new ArrayList<>();

        request.getAdUnitKeywords().forEach(i -> keywordList.add(new AdUnitKeyword(i.getUnitId(), i.getKeyword())));
        List<Long> idList = adUnitKeywordDao.saveAll(keywordList).stream().map(AdUnitKeyword::getId).collect(Collectors.toList());
        return new AdUnitKeywordResponse(idList);
    }

    @Override
    @Transactional
    public AdUnitItResponse createUnitIt(AdUnitItRequest request) throws AdException {
        List<Long> ids = request.getAdUnitIts().stream().
                map(AdUnitItRequest.UnitIt::getUnitId).collect(Collectors.toList());
        if (!isUnitExist(ids)){
            throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR);
        }
        List<AdUnitIt> keywordList = new ArrayList<>();

        request.getAdUnitIts().forEach(i -> keywordList.add(new AdUnitIt(i.getUnitId(), i.getItTag())));
        List<Long> idList = adUnitItDao.saveAll(keywordList).stream().map(AdUnitIt::getId).collect(Collectors.toList());

        return new AdUnitItResponse(idList);
    }

    @Override
    @Transactional
    public AdUnitDistrictResponse createUnitDistrict(AdUnitDistrictRequest request) throws AdException {
        List<Long> ids = request.getUnitDistricts().stream().
                map(AdUnitDistrictRequest.UnitDistrict::getUnitId).collect(Collectors.toList());
        if (!isUnitExist(ids)){
            throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR);
        }
        List<AdUnitDistrict> keywordList = new ArrayList<>();
        request.getUnitDistricts().forEach(i -> keywordList.add(new AdUnitDistrict(i.getUnitId(), i.getProvince(), i.getCity())));
        List<Long> idList = adUnitDistrictDao.saveAll(keywordList).stream().map(AdUnitDistrict::getId).collect(Collectors.toList());

        return new AdUnitDistrictResponse(idList);
    }

    @Override
    @Transactional
    public CreativeUnitResponse createCreativeUnit(CreativeUnitRequest request) throws AdException {
        List<Long> unitIds = request.getCreativeUnitList().stream().map(CreativeUnitRequest.CreativeUnitItem::getUnitId).collect(Collectors.toList());
        List<Long> creativeIds = request.getCreativeUnitList().stream().map(CreativeUnitRequest.CreativeUnitItem::getCreativeId).collect(Collectors.toList());
        if (!(isUnitExist(unitIds) && isCreativeExist(creativeIds))){
            throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR);
        }

        List<CreativeUnit> list = new ArrayList<>();
        request.getCreativeUnitList().forEach(i-> list.add(new CreativeUnit(i.getCreativeId(),i.getUnitId())));
        List<Long> ids = creativeUnitDao.saveAll(list).stream().map(CreativeUnit::getId).collect(Collectors.toList());


        return new CreativeUnitResponse(ids);
    }

    private boolean isUnitExist(List<Long> ids){
        if (CollectionUtils.isEmpty(ids)){
            return false;
        }
        return adUnitDao.findAllById(ids).size() == new HashSet<>(ids).size();
    }

    private boolean isCreativeExist(List<Long> ids){
        if (CollectionUtils.isEmpty(ids)){
            return false;
        }
        return creativeUnitDao.findAllById(ids).size() == new HashSet<>(ids).size();
    }
}
